package com.yima.baseproj.config.swagger;

import com.yima.baseproj.module.sys.login.model.LoginLoginModel;
import com.yima.baseproj.module.sys.login.SysLoginService;
import com.yima.baseproj.security.SecurityUtil;
import com.yima.baseproj.security.model.LoginClientEnum;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 打开：http://localhost:11020/server/doc.html
 * @Author 一码
 * @createDate 2023/4/1 09:00
 * @contact 1424529270@qq.com
 */
@Slf4j
@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Resource
    public SysLoginService sysLoginService;

    private List<ApiKey> securitySchemes() {
        List<ApiKey> apiKeys = new ArrayList<>();
        apiKeys.add(new ApiKey("Authorization", "Authorization", "header"));
        apiKeys.add(new ApiKey("client", "client", "header"));
        return apiKeys;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("^(?!auth).*$")).build());
        return securityContexts;
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }

    @Bean
    public Docket appApi() {
        Parameter tokenPar = new ParameterBuilder()
                .name("Authorization").defaultValue("")
                .modelRef(new ModelRef("String")).
                        parameterType("header").build();

        Parameter parameter = new ParameterBuilder()
                .name("client").description("客户端").defaultValue(LoginClientEnum.mp_weixin.name())
                .modelRef(new ModelRef("String")).
                        parameterType("header").required(true).build();

        return new Docket(DocumentationType.SWAGGER_2)
                .globalOperationParameters(Arrays.asList(tokenPar,parameter))
                .apiInfo(apiInfo())
                .groupName("APP接口")
                .select()
                // 扫描所有有注解的api，用这种方式更灵活
                .apis(RequestHandlerSelectors.basePackage("com.yima.baseproj.module.app"))
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    @Bean
    public Docket tmplApi() {
        Parameter tokenPar = new ParameterBuilder()
                .name("Authorization").defaultValue("")
                .modelRef(new ModelRef("String")).
                        parameterType("header").build();

        Parameter parameter = new ParameterBuilder()
                .name("client").description("客户端").defaultValue(LoginClientEnum.mp_weixin.name())
                .modelRef(new ModelRef("String")).
                        parameterType("header").required(true).build();

        return new Docket(DocumentationType.SWAGGER_2)
                .globalOperationParameters(Arrays.asList(tokenPar,parameter))
                .apiInfo(apiInfo())
                .groupName("Tmpl接口")
                .select()
                // 扫描所有有注解的api，用这种方式更灵活
                .apis(RequestHandlerSelectors.basePackage("com.yima.baseproj.module.tmpl"))
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    @Bean
    public Docket sysApi() {
        Parameter tokenPar = new ParameterBuilder()
                .name("Authorization").defaultValue(SecurityUtil.BEARER + sysLoginService.login(new LoginLoginModel("admin","123456")))
                .modelRef(new ModelRef("String")).
                        parameterType("header").required(true).build();

        Parameter clientPar = new ParameterBuilder()
                .name("client").description("客户端").defaultValue(LoginClientEnum.admin.name())
                .modelRef(new ModelRef("String")).
                        parameterType("header").required(true).build();

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("SYS接口")
                .globalOperationParameters(Arrays.asList(tokenPar,clientPar))
                .select()
                // 扫描所有有注解的api，用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .apis(RequestHandlerSelectors.basePackage("com.yima.baseproj.module.sys"))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    /**
     * Swagger界面内容配置
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("API接口文档")//标题
                .description("基础项目的接口文档，包含APP接口和后台管理系统接口")//描述
                .version("1.0.0")//版本
                .contact(new Contact(
                        "一码", //维护人
                        "https://yanwei.xin", //维护人URL
                        "1424529270@qq.com"))//维护人email
                .build();
    }
}
